#include "cardengine.h"
#include "cardspot.h"
#include "card.h"
#include <algorithm>

std::vector<CardEngine*> CardEngine::enginesVector;

CardEngine::CardEngine(const std::string &name, int type)
    : hoveredSpot(0), data(name, type)
{
}

CardEngine::~CardEngine()
{
    for (int i=cardSpots.size() - 1; i>=0; --i) {
        delete cardSpots[i];
    }
}

std::vector<CardEngine*> CardEngine::engines()
{
    return enginesVector;
}

void CardEngine::handlePress(const Point &pos)
{
    Card *card = cardAt(pos);
    if (card) {
//         if (card->cardSpot()) {
//             int index = card->cardSpot()
//             // heuristic that might not be true
//         }
        draggedCards.push_back(card);
//        dragOffset = pos - card->geometry().getMin();
        lastMove = pos;
    }
}

void CardEngine::handleDrag(const Point &pos)
{
    if (draggedCards.size()) {
        Rectangle total;
        for (std::vector<Card*>::const_iterator it = draggedCards.begin(); it != draggedCards.end(); ++it) {
            Rectangle rect = (*it)->geometry();
            rect.moveBy(pos - lastMove);
            (*it)->setGeometry(rect);
            total |= rect;
        }
//        std::vector<CardSpot*> spots = cardSpots
        lastMove = pos;
    }
}

void CardEngine::handleRelease(const Point &pos)
{
//     for (std::vector<Card*>::const_iterator it = draggedCards.begin(); it != draggedCards.end(); ++it) {
//         Rectangle rect = (it*)->geometry();
//         rect.moveBy(pos - lastMove);
//         it.setGeometry(rect);
//     }
//     lastMove = pos;
}

std::vector<CardSpot *> CardEngine::cardSpotsAt(const Rectangle &rect) const
{
    std::vector<CardSpot*> vector;
    enum { Count = 5 };
    const Point points[Count] = { rect.position(), rect.bottomRight(), rect.center(), rect.topRight(), rect.bottomLeft() };
    for (int i=0; i<Count; ++i) {
        CardSpot *spot = cardSpotAt(points[i]);
        if (spot) {
            vector.push_back(spot);
        }
    }
    return vector;
}

bool CardEngine::canDrop(const Card *card, const CardSpot *spot) const
{
    return spot->canDrop(card);
}

bool CardEngine::drop(Card *card, CardSpot *spot)
{
    return spot->drop(card);
}

void CardEngine::reset()
{
    for (int i=deck.size() - 1; i>=0; --i) {
        delete deck[i];
    }
    deck.clear();
    for (int i=inplay.size() - 1; i>=0; --i) {
        delete inplay[i];
    }
    inplay.clear();

    draggedCards.clear();
    hoveredSpot = 0;
    for (int i=0; i<52; ++i) { // customizable ###
        Card *card = new Card(static_cast<Card::Suit>(i / 14), (i % 14) + 1);
        card->flip(Card::FaceDown);
    }

    std::random_shuffle(deck.begin(), deck.end());
}

CardSpot *CardEngine::cardSpotAt(const Point &pos) const
{
    for (std::vector<CardSpot*>::const_iterator it = cardSpots.begin(); it != cardSpots.end(); ++it) {
        if ((*it)->geometry().contains(pos)) {
            return *it;
        }
    }
    return 0;
}

Card *CardEngine::cardAt(const Point &pos) const
{
    Card *best = 0;
    for (std::vector<Card*>::const_iterator it = inplay.begin(); it != inplay.end(); ++it) {
        if ((*it)->geometry().contains(pos) && (!best || (*it)->zValue() > best->zValue())) {
            best = *it;
        }
    }
    return 0;
}

Card *CardEngine::pop_deck()
{
    assert(deck.size() > 0);
    Card *ret = deck.back();
    deck.pop_back();
    return ret;
}

const std::string &CardEngine::name() const
{
    return data.name;
}

void CardEngine::windowResized(const Rectangle &)
{

}

std::vector<Card*> CardEngine::grabCard(Card *card) const
{

}
